package com.quwan.app.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.quwan.app.service.PaymentService;
import com.quwan.app.vo.PushOfflineMsgParams;
import com.quwan.app.vo.pay.NotifyProcessParams;
import com.quwan.common.BaseService;
import com.quwan.common.Check;
import com.quwan.common.ImMsgType;
import com.quwan.common.enums.*;
import com.quwan.common.exception.ExpCode;
import com.quwan.common.exception.PayException;
import com.quwan.common.exception.ResponseException;
import com.quwan.component.AsyncTaskComponent;
import com.quwan.component.ComponentFactory;
import com.quwan.component.TencentComponent;
import com.quwan.config.yml.PaymentBalanceConfig;
import com.quwan.constans.AppConst;
import com.quwan.entity.*;
import com.quwan.mapper.*;
import com.quwan.utils.DateUtils;
import com.quwan.utils.Parse;
import com.quwan.utils.redis.Redis;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.function.Predicate;


/**
 * @author quan
 * @date 2021-06-19 15:18
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class PaymentServiceImpl extends BaseService implements PaymentService {
    private final C2cOrderMapper orderMapper;
    private final TMemberMapper memberMapper;
    private final TSystemPrePayMapper systemPrePayMapper;
    private final TMemberBalanceLogMapper balanceLogMapper;
    private final TRechargeVipMapper rechargeVipMapper;
    private final TVipRuleMapper vipRuleMapper;
    private final TMemberVipMapper memberVipMapper;
    private final PasswordEncoder passwordEncoder;
    private final TPublishOrderMapper publishOrderMapper;
    private final TDdLogMapper ddLogMapper;
    private final AsyncTaskComponent taskComponent;
    private final Redis redis;
    private final PaymentBalanceConfig balanceConfig;
    private final ComponentFactory componentFactory;
    private final TDispatchOrderMapper dispatchOrderMapper;
    private final TDispatchOrderApplyMapper applyMapper;
    private final TGuestAppleBuyMapper appleBuyMapper;
    private final TencentComponent tencentComponent;

    @Value("${msg.buyIt.title}")
    private String buyItTitle;
    @Value("${msg.buyIt.content}")
    private String buyItContent;
    @Value("${msg.dispatch.choose}")
    private String chooseMsg;
    @Value("${msg.process.chatMsg}")
    private String chatMsg;

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    @Override
    public boolean updOrderPayFinishInfo(NotifyProcessParams notifyProcessParams) {
        final String transactionId = notifyProcessParams.getTransactionId();
        final String consumeOrderId = notifyProcessParams.getOrderId();
        final String money = notifyProcessParams.getMoney();

        C2cOrder order = orderMapper
                .selectOne(
                        new LambdaQueryWrapper<C2cOrder>()
                                .select(C2cOrder::getPayStatus, C2cOrder::getMId, C2cOrder::getPayPrice, C2cOrder::getPublishOrderId, C2cOrder::getTransactionId, C2cOrder::getCouponPrice, C2cOrder::getCouponStatus, C2cOrder::getBeginTime)
                                .eq(C2cOrder::getId, consumeOrderId)
                );
        log.info("支付回执:consumeOrderId::{}", consumeOrderId);
        Check.notNull(order, ExpCode.ORDER_NOT_EXIST);
        if ("prod".equalsIgnoreCase(componentFactory.getActiveProfile())) {
            if (order.getPayPrice().compareTo(new BigDecimal(money)) != 0) {
                log.error("支付金额 与订单金额不匹配:orderPrice::{},payMoney:{}", order.getPayPrice(), money);
                return false;
            }
        }

        if (PayStatusEnum.FINISH.getType().equals(order.getPayStatus()) && StringUtils.isNotBlank(order.getTransactionId())) {
            log.info("updOrderPayFinishInfo 已经处理过的支付回执 consumeOrderId::{}", consumeOrderId);
            return true;
        }

        //修改订单状态->支付完成
        int orderRow =
                orderMapper
                        .update(null,
                                new LambdaUpdateWrapper<C2cOrder>()
                                        .set(C2cOrder::getPayStatus, PayStatusEnum.FINISH.getType())
                                        .set(C2cOrder::getTransactionId, transactionId)
                                        .set(C2cOrder::getPayTime, new Date())
                                        .eq(C2cOrder::getId, consumeOrderId)
                        );

        if (orderRow == 1) {
            //订单是否有优惠信息
            if (order.getCouponStatus().equals(AppConst.COUPON_DD) && order.getCouponPrice().compareTo(BigDecimal.ZERO) > 0) {
                //记录优惠日志
                ddLogMapper.insert(
                        new TDdLog()
                                .setTips("订单优惠")
                                .setTradeNo(consumeOrderId)
                                .setDay(LocalDate.now())
                                .setType(0)
                                .setMId(order.getMId())
                                .setDd(order.getCouponPrice().multiply(AppConst.b100).longValue())
                );
            }
            try {

                _computeOrderAutoCancel(consumeOrderId, order.getBeginTime());
                //查询发单人信息
                TPublishOrder publishOrder = publishOrderMapper
                        .selectOne(
                                new LambdaQueryWrapper<TPublishOrder>()
                                        .select(TPublishOrder::getMId)
                                        .eq(TPublishOrder::getId, order.getPublishOrderId())
                        );
                //推送用户下单消息 -> 发单人
                Integer count = publishOrderMapper.selectNotProcessOrderCount(publishOrder.getMId());
                PushOfflineMsgParams params =
                        pushOffLineMsg(publishOrder.getMId(),
                                AppConst.CAT_CONSUMER_TYPE,
                                consumeOrderId,
                                buyItTitle,
                                buyItContent.replace("@", count + ""),
                                AppConst.OFFLINE_MSG_ORDER_BUYIT);
                taskComponent.pushOfflineMsgToMember(params);
                TMember member = memberMapper.selectOne(new QueryWrapper<>(new TMember().setId(publishOrder.getMId())));
                if (member != null && StringUtils.isNotBlank(member.getMobile()))
                    tencentComponent.sendOrderSms(member.getMobile());
            } catch (Exception e) {
                log.error("updOrderPayFinishInfo exp::{}", e.getMessage());
            }
        } else {
            log.error("订单支付信息状态修改失败orderId::{}", order);
            return false;
        }

        return true;
    }


    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    @Override
    public boolean updVipPayFinishInfo(NotifyProcessParams notifyProcessParams) {
        final String orderId = notifyProcessParams.getOrderId();
        final String transactionId = notifyProcessParams.getTransactionId();
        final String money = notifyProcessParams.getMoney();
        TRechargeVip rechargeInfo =
                rechargeVipMapper
                        .selectOne(
                                new LambdaQueryWrapper<TRechargeVip>()
                                        .select(TRechargeVip::getMId, TRechargeVip::getVipId, TRechargeVip::getStatus, TRechargeVip::getTransactionId, TRechargeVip::getMoney)
                                        .eq(TRechargeVip::getRechargeSlipNum, orderId)
                        );
        if (rechargeInfo == null) {
            log.info("rechargeInfo 信息查询异常 null RechargeSlipNum::{}", orderId);
            return false;
        }
        if (PayStatusEnum.FINISH.getType().equals(rechargeInfo.getStatus()) && StringUtils.isNotBlank(transactionId)) {
            log.info("updVipPayFinishInfo 已经处理过的支付回执 RechargeSlipNum::{}", orderId);
            return true;
        }
        //todo 金额校验
        Long vipId = rechargeInfo.getVipId();
        TVipRule vipRule = vipRuleMapper.selectById(vipId);
        Check.notNull(vipRule, ExpCode.DATA_SELECT_NULL);
        Integer months = vipRule.getTime();
        LocalDateTime now = LocalDateTime.now();
        TMemberVip memberVip = memberVipMapper.selectOne(
                new LambdaQueryWrapper<TMemberVip>()
                        .select(TMemberVip::getId, TMemberVip::getEndTime)
                        .eq(TMemberVip::getMId, rechargeInfo.getMId())
                        .orderByDesc(TMemberVip::getEndTime)
                        .last(" limit 1")
        );
        if (memberVip != null && memberVip.getEndTime().isAfter(now))
            //当前会员是vip 并且 vip结束时间大于当前时间 续费时间vip
            now = memberVip.getEndTime();

        int vipRow = memberVipMapper
                .insert(
                        new TMemberVip()
                                .setBeginTime(now)
                                .setEndTime(months==0?now.plusDays(1):now.plusMonths(months))
                                .setUniqueLock(orderId)
                                .setVId(vipId)
                                .setMId(rechargeInfo.getMId())

                );
        int rechargeRow = rechargeVipMapper
                .update(null,
                        new LambdaUpdateWrapper<TRechargeVip>()
                                .set(TRechargeVip::getStatus, PayStatusEnum.FINISH.getType())
                                .set(TRechargeVip::getTransactionId, transactionId)
                                .set(TRechargeVip::getPayTime,new Date())
                                .eq(TRechargeVip::getRechargeSlipNum, orderId)
                );
        if (rechargeRow != 1) {
            log.error("用户vip充值 支付状态修改失败 RechargeSlipNum::{},mId::{}", orderId, rechargeInfo.getMId());
            throw new ResponseException(ExpCode.DB_UPDATE_ERR.getCode(), ExpCode.DB_UPDATE_ERR.getMsg());
        }
        if (vipRow != 1) {
            log.error("用户vip充值 更新用户vip数据失败 RechargeSlipNum::{},mId::{}", orderId, rechargeInfo.getMId());
            throw new ResponseException(ExpCode.DB_UPDATE_ERR.getCode(), ExpCode.DB_UPDATE_ERR.getMsg());
        }

        return true;
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    @Override
    public boolean updRechargeBalanceFinishInfo(NotifyProcessParams notifyProcessParams) {
        final String orderId = notifyProcessParams.getOrderId();
        final String transactionId = notifyProcessParams.getTransactionId();
        final String money = notifyProcessParams.getMoney();
        TMemberBalanceLog rechargeBalanceLog = balanceLogMapper.selectOne(
                new LambdaQueryWrapper<TMemberBalanceLog>()
                        .select(TMemberBalanceLog::getMId, TMemberBalanceLog::getTradeNo, TMemberBalanceLog::getTransactionId, TMemberBalanceLog::getMoney, TMemberBalanceLog::getStatus)
                        .eq(TMemberBalanceLog::getTradeNo, orderId)
        );
        if (rechargeBalanceLog == null) {
            log.error("充值余额账单查询异常 tradeNo::{}", orderId);
            return false;
        }
        if (PayStatusEnum.FINISH.getType().equals(rechargeBalanceLog.getStatus()) && StringUtils.isNotBlank(rechargeBalanceLog.getTransactionId())) {
            log.info("updRechargeBalanceFinishInfo 已经处理过的支付回执 tradeNo::{}", orderId);
            return true;
        }
        //todo 金额校验

        TMember member = memberMapper.selectOne(
                new LambdaQueryWrapper<TMember>()
                        .select(TMember::getVersion, TMember::getBalance)
                        .eq(TMember::getId, rechargeBalanceLog.getMId())
        );
        if (member == null) {
            log.error("余额充值用户信息查询失败 null mid::{},tradeNo::{}", rechargeBalanceLog.getMId(), orderId);
            return false;
        }
        BigDecimal balance = member.getBalance();
        Long version = member.getVersion();
        BigDecimal finalBalance = balance.add(new BigDecimal(money));
        int logRow = balanceLogMapper.update(
                null,
                new LambdaUpdateWrapper<TMemberBalanceLog>()
                        .set(TMemberBalanceLog::getStatus, PayStatusEnum.FINISH.getType())
                        .set(TMemberBalanceLog::getTransactionId, transactionId)
                        .set(TMemberBalanceLog::getBeforeM, balance)
                        .set(TMemberBalanceLog::getBalance, finalBalance)
                        .set(TMemberBalanceLog::getPayTime, LocalDateTime.now())
                        .eq(TMemberBalanceLog::getTradeNo, orderId)
        );
        int memberRow = memberMapper.update(
                null,
                new LambdaUpdateWrapper<TMember>()
                        .set(TMember::getBalance, finalBalance)
                        .set(TMember::getVersion, version + 1)
                        .eq(TMember::getId, rechargeBalanceLog.getMId())
                        .eq(TMember::getVersion, version)
        );
        if (memberRow != 1) {
            log.error("更新用户充值余额 金额添加失败 tradeNo::{},mId::{},money::{}", orderId, rechargeBalanceLog.getMId(), money);
            throw new ResponseException(ExpCode.DB_UPDATE_ERR.getCode(), ExpCode.DB_UPDATE_ERR.getMsg());
        }
        if (logRow != 1) {
            log.error("更新用户余额记录失败  tradeNo::{},mId::{},money::{}", orderId, rechargeBalanceLog.getMId(), money);
            throw new ResponseException(ExpCode.DB_UPDATE_ERR.getCode(), ExpCode.DB_UPDATE_ERR.getMsg());
        }
        return true;

    }


    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    @Override
    public boolean updBeforeDispatchOrderPayFinishInfo(NotifyProcessParams notifyProcessParams) {

        final String orderId = notifyProcessParams.getOrderId();
        final String transactionId = notifyProcessParams.getTransactionId();
        final String money = notifyProcessParams.getMoney();

        TDispatchOrder order = dispatchOrderMapper.selectOne(
                new QueryWrapper<>(new TDispatchOrder().setOrderId(Parse.toLong(orderId))));


        if (order == null) {
            log.info("dispatchOrder 信息查询异常 null orderId::{}", orderId);
            return false;
        }
        if (PayStatusEnum.FINISH.getType().equals(order.getBeforeStatus()) && StringUtils.isNotBlank(order.getBeforeTransactionId())) {
            log.info("updBeforeDispatchOrderPayFinishInfo 已经处理过的支付回执 orderId::{}", orderId);
            return true;
        }
        //DONE 金额校验

        if ("prod".equalsIgnoreCase(componentFactory.getActiveProfile())) {
            if (order.getBeforePrice().compareTo(new BigDecimal(money)) != 0) {
                log.error("支付金额 与订单金额不匹配:orderPrice::{},payMoney:{}", order.getBeforePrice(), money);
                return false;
            }
        }


        //修改订单状态->支付完成
        int orderRow =
                dispatchOrderMapper
                        .update(null,
                                new LambdaUpdateWrapper<TDispatchOrder>()
                                        .set(TDispatchOrder::getBeforeStatus, PayStatusEnum.FINISH.getType())
                                        .set(TDispatchOrder::getBeforeTransactionId, transactionId)
                                        .set(TDispatchOrder::getStatus, DispatchOrderStatusEnum.await.getStatus())
                                        .set(TDispatchOrder::getPayTime, LocalDateTime.now())

                                        .eq(TDispatchOrder::getOrderId, orderId)
                        );

        return orderRow == 1;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    @Override
    public boolean updDispatchOrderPayFinishInfo(NotifyProcessParams notifyProcessParams) {

        final String orderId = notifyProcessParams.getOrderId();
        final String transactionId = notifyProcessParams.getTransactionId();
        final String money = notifyProcessParams.getMoney();

        TDispatchOrder order = dispatchOrderMapper.selectOne(
                new QueryWrapper<>(new TDispatchOrder().setId(Parse.toLong(orderId))));


        if (order == null) {
            log.info("dispatchOrder 信息查询异常 null id::{}", orderId);
            return false;
        }
        if (PayStatusEnum.FINISH.getType().equals(order.getPayStatus()) && StringUtils.isNotBlank(order.getTransactionId())) {
            log.info("updDispatchOrderPayFinishInfo 已经处理过的支付回执 orderId::{}", orderId);
            return true;
        }
        //DONE 金额校验

        if ("prod".equalsIgnoreCase(componentFactory.getActiveProfile())) {
            if (order.getAfterPrice().compareTo(new BigDecimal(money)) != 0) {
                log.error("支付金额 与订单金额不匹配:orderPrice::{},payMoney:{}", order.getAfterPrice(), money);
                return false;
            }
        }


        //修改订单状态->支付完成
        int orderRow =
                dispatchOrderMapper
                        .update(null,
                                new LambdaUpdateWrapper<TDispatchOrder>()
                                        .set(TDispatchOrder::getPayStatus, PayStatusEnum.FINISH.getType())
                                        .set(TDispatchOrder::getTransactionId, transactionId)
                                        .set(TDispatchOrder::getStatus, DispatchOrderStatusEnum.processing.getStatus())
                                        .set(TDispatchOrder::getConfirmTime, LocalDateTime.now())
                                        .set(TDispatchOrder::getAudit,1)
                                        .eq(TDispatchOrder::getId, orderId)
                        );

        //支付完成 已申请用户数据状态失效
        applyMapper.update(null,
                new LambdaUpdateWrapper<TDispatchOrderApply>()
                        .set(TDispatchOrderApply::getStatus, DispatchOrderStatusEnum.del.getStatus())
                        .eq(TDispatchOrderApply::getOrderId, order.getId())
                        .ne(TDispatchOrderApply::getApplyMId, order.getServiceId())
        );
        applyMapper.update(
                null,
                new LambdaUpdateWrapper<TDispatchOrderApply>()
                        .set(TDispatchOrderApply::getStatus, DispatchOrderStatusEnum.processing.getStatus())
                        .eq(TDispatchOrderApply::getOrderId, order.getId())
                        .eq(TDispatchOrderApply::getApplyMId, order.getServiceId())
        );
        if (orderRow == 1) {
            PushOfflineMsgParams params =
                    pushOffLineMsg(order.getServiceId(),
                            null,
                            order.getId().toString(),
                            chooseMsg,
                            chooseMsg,
                            AppConst.OFFLINE_MSG_DISPATCH_ORDER_ORDER_CHOOSE);
            taskComponent.pushOfflineMsgToMember(params);
            tencentComponent
                    .singlePushMsg(2, order.getServiceId().toString(),
                            order.getMId().toString(),
                            order.getMId().toString(), ImMsgType.text.getCode(), chatMsg);
        }
        return orderRow == 1;
    }

    @Override
    public void doGrantVip(String id, JSONObject data) {
        AppleProductEnum productEnum = AppleProductEnum.getByType(data.getString("product_id"));
        Check.notNull(productEnum, ExpCode.DATA_ILLEGAL);
        Integer vipId = productEnum.getId();
        String transactionId = data.getString("transaction_id");
        TVipRule vipRule = vipRuleMapper.selectById(vipId);
        if (vipRule == null) return;

        Integer months = vipRule.getTime();
        LocalDateTime now = LocalDateTime.now();
        TMemberVip memberVip = memberVipMapper.selectOne(
                new LambdaQueryWrapper<TMemberVip>()
                        .select(TMemberVip::getId, TMemberVip::getEndTime)
                        .eq(TMemberVip::getMId, id)
                        .orderByDesc(TMemberVip::getEndTime)
                        .last(" limit 1")
        );
        if (memberVip != null && memberVip.getEndTime().isAfter(now))
            //当前会员是vip 并且 vip结束时间大于当前时间 续费时间vip
            now = memberVip.getEndTime();

        int vipRow = memberVipMapper
                .insert(
                        new TMemberVip()
                                .setBeginTime(now)
                                .setEndTime(months==0?now.plusDays(1):  now.plusMonths(months))
                                .setUniqueLock(transactionId)
                                .setVId(Parse.toLong(vipId))
                                .setMId(Parse.toLong(id))

                );
        int rechargeRow = rechargeVipMapper
                .insert(
                        new TRechargeVip()
                                .setPrePayId(transactionId)
                                .setTransactionId(transactionId)
                                .setPayTime(new Date())
                                .setPayMethod(-1)
                                .setStatus(1)
                                .setVipId(Parse.toLong(vipId))
                                .setMId(Parse.toLong(id))
                                .setRechargeSlipNum(transactionId)
                                .setMoney(vipRule.getPrice())
                );
        if (rechargeRow != 1) {
            log.error("Apple 用户vip充值 数据添加失败 RechargeSlipNum::{},mId::{}", transactionId, id);
            throw new ResponseException(ExpCode.DB_UPDATE_ERR.getCode(), ExpCode.DB_UPDATE_ERR.getMsg());
        }
        if (vipRow != 1) {
            log.error("Apple 用户vip充值 更新用户vip数据失败 RechargeSlipNum::{},mId::{}", transactionId, id);
            throw new ResponseException(ExpCode.DB_UPDATE_ERR.getCode(), ExpCode.DB_UPDATE_ERR.getMsg());
        }
        log.info("Apple pay success ::{}", transactionId);
    }

    @Override
    public void recordUniqueInfo(String unique, JSONObject data) {
        if (appleBuyMapper.insert(new TGuestAppleBuy().setKey(unique).setData(data.toJSONString())) != 1)
            log.error("add apple guest buy fail::unique::{},data::{} ", unique, data.toJSONString());
    }

    /**
     * 计算订单自动取消时间
     *
     * @param orderId
     * @param time
     */
    private void _computeOrderAutoCancel(String orderId, LocalDateTime time) {
        LocalDateTime now = LocalDateTime.now();
        if (StringUtils.isBlank(orderId) || time == null || now.isAfter(time))
            return;
        Long seconds = DateUtils.computeSecond(now, time);
        redis.setListener(RedisListenerEnum.cancel_not_process_order.getKey() + RedisListenerEnum.split + orderId, 0, seconds);

    }

    /**
     * 校验预支付id
     *
     * @param orderId
     * @param preId
     */
    private void _authPayPreId(String orderId, String preId) {
        long currTime = System.currentTimeMillis();
        //预支付流程生成规则 orderid -currentTimeMillis
        long authTime = Long.parseLong(orderId) - currTime;
        //校验超时 预支付流水 -  （orderid-currentTimeMillis）大于 超时
        if (Long.parseLong(preId) - authTime > balanceConfig.getTimeOut() * 1000) {
            systemPrePayMapper
                    .delete(new QueryWrapper<>(
                            new TSystemPrePay()
                                    .setTradNo(Long.parseLong(orderId))
                                    .setStatus(PayStatusEnum.NOT.getType())
                    ));
            throw new ResponseException(ExpCode.PAY_TIME_OUT.getCode(), ExpCode.PAY_TIME_OUT.getMsg());//支付信息过期
        }

    }

    /**
     * 余额支付 用户金额处理
     *
     * @param orderId  支付订单id
     * @param preId    预支付id
     * @param memberId process 业务处理逻辑
     * @param type     0消费 1会员充值
     * @param payPwd
     * @param process
     */
    @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRES_NEW)
    @Override
    public void doBalancePay(String orderId, String preId, String memberId, String type, String payPwd, Predicate<TSystemPrePay> process) {
        //鉴定支付时间是否超时
        _authPayPreId(orderId, preId);
        //查询支付会员信息
        TMember member =
                memberMapper
                        .selectOne(
                                new LambdaQueryWrapper<TMember>()
                                        .select(TMember::getVersion, TMember::getId, TMember::getBalance, TMember::getPayPwd)
                                        .eq(TMember::getId, memberId)
                        );

        Check.notNull(member, ExpCode.MEMBER_NOT_EXIST);

        //预支付流水是否存在
        TSystemPrePay prePayInfo = systemPrePayMapper.selectOne(new QueryWrapper<>(
                new TSystemPrePay()
                        .setPreId(Long.parseLong(preId))
                        .setTradNo(Long.parseLong(orderId))
                        .setMId(member.getId()))
        );

        Check.notNull(prePayInfo, ExpCode.PAY_TIME_OUT);//预支付信息 null 判定重新支付


        if (PayStatusEnum.FINISH.getType().equals(prePayInfo.getStatus()))
            return;
        //校验支付密码
        _authPayPassword(payPwd, member.getPayPwd());
        BigDecimal prepayPrice = prePayInfo.getMoney();
        BigDecimal memberBalance = member.getBalance();
        BigDecimal balance = memberBalance.subtract(prepayPrice);
        //支付金额是否大于余额
        if (BigDecimal.ZERO.compareTo(balance) > 0)//余额不足
            throw new ResponseException(ExpCode.PAY_BALANCE_LESS.getCode(), ExpCode.PAY_BALANCE_LESS.getMsg());

        Long version = member.getVersion();
        int memberRow =  //扣除支付金额
                memberMapper
                        .update(null,
                                new LambdaUpdateWrapper<TMember>()
                                        .set(TMember::getBalance, balance)
                                        .set(TMember::getVersion, version + 1)
                                        .eq(TMember::getId, memberId)
                                        .eq(TMember::getVersion, version)
                        );
        //修改预支付状态 -> 支付完成
        int prepayRow =
                systemPrePayMapper
                        .updateById(
                                new TSystemPrePay()
                                        .setTransactionId(prePayInfo.getTransactionId())
                                        .setStatus(PayStatusEnum.FINISH.getType())
                        );
        //余额日志添加
        int logRow =
                balanceLogMapper
                        .insert(new TMemberBalanceLog()
                                .setMId(member.getId())
                                .setTips(BalancePayTypeEnum.getByType(type).getTips())
                                .setTradeType(BalancePayTypeEnum.getByType(type).getTradeType())
                                .setStatus(PayStatusEnum.FINISH.getType())
                                .setPrePayId(preId)
                                .setBalance(balance)
                                .setMoney(prepayPrice)
                                .setBeforeM(memberBalance)
                                .setMethod(Integer.parseInt(PaymentEnum.SYSTEM_PAY.getType()))
                                .setTradeNo(orderId)
                                .setPayTime(LocalDateTime.now())
                                .setTransactionId(prePayInfo.getTransactionId() + "")
                        );

        if (!(memberRow == 1 && prepayRow == 1 && logRow == 1)) {
            log.error("系统支付 数据更新失败,支付订单::{} prepayId::{} memberId::{}", orderId, preId, memberId);
            throw new PayException(ExpCode.PAY_BALANCE_FAIL.getCode(), ExpCode.PAY_BALANCE_FAIL.getMsg());
        } else {
            //支付成功 处理业务逻辑
            boolean success = process.test(prePayInfo);
            if (!success) {
                log.error("system pay-->finishOrderStatus err orderId::{},type::{}", orderId, type);
                throw new PayException(ExpCode.PAY_BALANCE_FAIL.getCode(), ExpCode.PAY_BALANCE_FAIL.getMsg());
            }
            log.info("余额支付处理：orderId::{}", orderId);


        }

    }

    private void _authPayPassword(String rawPassword, String realPassword) {

        Check.state(passwordEncoder.matches(rawPassword, realPassword), ExpCode.PAY_PASSWORD_NOT_MATCHES);
    }


}
